/**
 * 通用组件共同的使用的基础组件，原先放在 adapter/form 内部，限制了使用范围，这里提取出来，方便其他地方使用
 * 可用于 jcx-form、jcx-modal、jcx-drawer 等组件使用,
 */

import type {BaseFormComponentType} from '@/components/effects/ui';
import type {Recordable} from '@/typings/core';

import type {Component, SetupContext} from 'vue';
import {h} from 'vue';

import {ApiComponent, globalShareState, IconPicker} from '@/components/effects/ui';
import {$t} from '@/locales/effects';

import {
    ElButton,
    ElCheckbox,
    ElCheckboxButton,
    ElCheckboxGroup,
    ElDatePicker,
    ElDivider,
    ElInput,
    ElInputNumber,
    ElNotification,
    ElRadio,
    ElRadioButton,
    ElRadioGroup,
    ElSelectV2,
    ElSpace,
    ElSwitch,
    ElTimePicker,
    ElTreeSelect,
    ElUpload,
} from 'element-plus';

const withDefaultPlaceholder = <T extends Component>(
    component: T,
    type: 'input' | 'select',
) => {
    return (props: any, {attrs, slots}: Omit<SetupContext, 'expose'>) => {
        const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`);
        return h(component, {...props, ...attrs, placeholder}, slots);
    };
};

// 这里需要自行根据业务组件库进行适配，需要用到的组件都需要在这里类型说明
export type ComponentType =
    | 'ApiSelect'
    | 'ApiTreeSelect'
    | 'Checkbox'
    | 'CheckboxGroup'
    | 'DatePicker'
    | 'Divider'
    | 'IconPicker'
    | 'Input'
    | 'InputNumber'
    | 'RadioGroup'
    | 'Select'
    | 'Space'
    | 'Switch'
    | 'TimePicker'
    | 'TreeSelect'
    | 'Upload'
    | BaseFormComponentType;

async function initComponentAdapter() {
    const components: Partial<Record<ComponentType, Component>> = {
        // 如果你的组件体积比较大，可以使用异步加载
        // Button: () =>
        // import('xxx').then((res) => res.Button),
        ApiSelect: (props, {attrs, slots}) => {
            return h(
                ApiComponent,
                {
                    placeholder: $t('ui.placeholder.select'),
                    ...props,
                    ...attrs,
                    component: ElSelectV2,
                    loadingSlot: 'loading',
                    visibleEvent: 'onVisibleChange',
                },
                slots,
            );
        },
        ApiTreeSelect: (props, {attrs, slots}) => {
            return h(
                ApiComponent,
                {
                    placeholder: $t('ui.placeholder.select'),
                    ...props,
                    ...attrs,
                    component: ElTreeSelect,
                    props: {label: 'label', children: 'children'},
                    nodeKey: 'value',
                    loadingSlot: 'loading',
                    optionsPropName: 'data',
                    visibleEvent: 'onVisibleChange',
                },
                slots,
            );
        },
        Checkbox: ElCheckbox,
        CheckboxGroup: (props, {attrs, slots}) => {
            let defaultSlot;
            if (Reflect.has(slots, 'default')) {
                defaultSlot = slots.default;
            } else {
                const {options, isButton} = attrs;
                if (Array.isArray(options)) {
                    defaultSlot = () =>
                        options.map((option) =>
                            h(isButton ? ElCheckboxButton : ElCheckbox, option),
                        );
                }
            }
            return h(
                ElCheckboxGroup,
                {...props, ...attrs},
                {...slots, default: defaultSlot},
            );
        },
        // 自定义默认按钮
        DefaultButton: (props, {attrs, slots}) => {
            return h(ElButton, {...props, attrs, type: 'info'}, slots);
        },
        // 自定义主要按钮
        PrimaryButton: (props, {attrs, slots}) => {
            return h(ElButton, {...props, attrs, type: 'primary'}, slots);
        },
        Divider: ElDivider,
        IconPicker: (props, {attrs, slots}) => {
            return h(
                IconPicker,
                {
                    iconSlot: 'append',
                    modelValueProp: 'model-value',
                    inputComponent: ElInput,
                    ...props,
                    ...attrs,
                },
                slots,
            );
        },
        Input: withDefaultPlaceholder(ElInput, 'input'),
        InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
        RadioGroup: (props, {attrs, slots}) => {
            let defaultSlot;
            if (Reflect.has(slots, 'default')) {
                defaultSlot = slots.default;
            } else {
                const {options} = attrs;
                if (Array.isArray(options)) {
                    defaultSlot = () =>
                        options.map((option) =>
                            h(attrs.isButton ? ElRadioButton : ElRadio, option),
                        );
                }
            }
            return h(
                ElRadioGroup,
                {...props, ...attrs},
                {...slots, default: defaultSlot},
            );
        },
        Select: (props, {attrs, slots}) => {
            return h(ElSelectV2, {...props, attrs}, slots);
        },
        Space: ElSpace,
        Switch: ElSwitch,
        TimePicker: (props, {attrs, slots}) => {
            const {name, id, isRange} = props;
            const extraProps: Recordable<any> = {};
            if (isRange) {
                if (name && !Array.isArray(name)) {
                    extraProps.name = [name, `${name}_end`];
                }
                if (id && !Array.isArray(id)) {
                    extraProps.id = [id, `${id}_end`];
                }
            }
            return h(
                ElTimePicker,
                {
                    ...props,
                    ...attrs,
                    ...extraProps,
                },
                slots,
            );
        },
        DatePicker: (props, {attrs, slots}) => {
            const {name, id, type} = props;
            const extraProps: Recordable<any> = {};
            if (type && type.includes('range')) {
                if (name && !Array.isArray(name)) {
                    extraProps.name = [name, `${name}_end`];
                }
                if (id && !Array.isArray(id)) {
                    extraProps.id = [id, `${id}_end`];
                }
            }
            return h(
                ElDatePicker,
                {
                    ...props,
                    ...attrs,
                    ...extraProps,
                },
                slots,
            );
        },
        TreeSelect: withDefaultPlaceholder(ElTreeSelect, 'select'),
        Upload: ElUpload,
    };

    // 将组件注册到全局共享状态中
    globalShareState.setComponents(components);

    // 定义全局共享状态中的消息提示
    globalShareState.defineMessage({
        // 复制成功消息提示
        copyPreferencesSuccess: (title, content) => {
            ElNotification({
                title,
                message: content,
                position: 'bottom-right',
                duration: 0,
                type: 'success',
            });
        },
    });
}

export {initComponentAdapter};
